import { Spin } from 'antd';
import { FC, HTMLAttributes, useEffect, useRef, useState } from 'react';
import { ApiConfig } from '@/typings';

// @ts-ignore
import BpmnJS from 'bpmn-js/dist/bpmn-navigated-viewer.production.min.js';
import { getTempData } from '@/biz-components/_common/wrapXhr';
import { DataIndex, getPathValue } from '@/biz-components/_common/valueUtil';

export interface BpmDiagramViewProps extends HTMLAttributes<any> {
  api?: ApiConfig;
  width?: CSSStyleDeclaration['width'];
  height?: CSSStyleDeclaration['height'];
  onError?: (error: any) => void;
  onWarning?: (warning: any) => {};
  value?: string;
  XMLDataPath?: DataIndex;
}

const BpmDiagramView: FC<BpmDiagramViewProps> = ({
  api,
  width,
  height,
  className,
  style,
  onError,
  onWarning,
  value: propsDiagramXML,
  XMLDataPath,
  ...restProps
}) => {
  const [loading, setLoading] = useState(false);

  const [diagramXML, setDiagramXML] = useState(propsDiagramXML);

  const containerRef = useRef<HTMLDivElement>(null);
  const bpmnViewerRef = useRef<any>(null);

  useEffect(() => {
    setDiagramXML(propsDiagramXML);
  }, [propsDiagramXML]);

  useEffect(() => {
    const { method, params, url } = api || {};

    if (!(method && url)) return;

    setLoading(true);
    getTempData({
      type: method,
      params,
      url,
    })
      .then((result: any) => {
        setLoading(false);

        const processModelXml = getPathValue<string, any>(result, XMLDataPath);

        setDiagramXML(processModelXml || '');
      })
      .catch(() => {
        setLoading(false);
      });
  }, [api]);

  useEffect(() => {
    if (!containerRef.current) return;

    bpmnViewerRef.current = new BpmnJS({
      container: containerRef.current,
    });

    bpmnViewerRef.current.on('import.done', (event) => {
      const { error, warnings } = event;

      if (error) {
        onError?.(error);
        return;
      }

      bpmnViewerRef.current.get('canvas').zoom('fit-viewport');

      onWarning?.(warnings);
    });
    return () => {
      bpmnViewerRef.current.destroy();
    };
  }, [containerRef]);

  useEffect(() => {
    if (!bpmnViewerRef.current) return;

    bpmnViewerRef.current.importXML(diagramXML);
  }, [diagramXML, bpmnViewerRef]);

  return (
    <Spin spinning={loading}>
      <div
        className={`bpmn-diagram-container ${className || ''}`}
        ref={containerRef}
        style={{
          ...style,
          height,
          width,
        }}
        {...restProps}
      />
    </Spin>
  );
};

BpmDiagramView.defaultProps = {
  height: '300px',
  width: '100%',
};

export default BpmDiagramView;
